package cn.fintecher.pangolin.service.dataimp.task;

import cn.fintecher.pangolin.common.enums.ImportDataExcelStatus;
import cn.fintecher.pangolin.common.enums.ImportTemplateType;
import cn.fintecher.pangolin.common.enums.MessageType;
import cn.fintecher.pangolin.common.exception.BadRequestException;
import cn.fintecher.pangolin.common.model.UserModel;
import cn.fintecher.pangolin.common.utils.SaxParseExcelUtil;
import cn.fintecher.pangolin.common.utils.ZWDateUtil;
import cn.fintecher.pangolin.entity.elastic.*;
import cn.fintecher.pangolin.service.dataimp.elastic.*;
import cn.fintecher.pangolin.service.dataimp.model.ImportModel;
import cn.fintecher.pangolin.service.dataimp.service.BaseService;
import cn.fintecher.pangolin.common.utils.RepositoryUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @Auther: xiaqun
 * @Description:
 * @Date: 17:39 2019/10/11
 */

@Service("ImportCommonTask")
public class ImportCommonTask {
    private static final Logger log = LoggerFactory.getLogger(ImportCommonTask.class);

    @Autowired
    private BaseService baseService;

    @Autowired
    private DataImportRecordElastic dataImportRecordElastic;

    @Autowired
    private PaymentRecordModelElastic paymentRecordModelElastic;

    @Autowired
    private PreRecordModelElastic preRecordModelElastic;

    @Autowired
    private WorkOrderModelElastic workOrderModelElastic;

    @Autowired
    private WarningModelElastic warningModelElastic;

    @Autowired
    private LeaveCaseModelElastic leaveCaseModelElastic;

    @Autowired
    private StopCaseModelElastic stopCaseModelElastic;

    @Autowired
    private ImportBillFuture importBillFuture;

    @Autowired
    private ImportPreFuture importPreFuture;

    @Autowired
    private ImportWorkOrderFuture importWorkOrderFuture;

    @Autowired
    private ImportWarningFuture importWarningFuture;

    @Autowired
    private ImportLeaveFuture importLeaveFuture;

    @Autowired
    private ImportStopFuture importStopFuture;

    @Async
    @Transactional
    public void processCommonImport(InputStream inputStream, ImportTemplate importTemplate, DataImportRecord record, String batchNumber, ImportTemplateType type, UserModel userModel) throws IOException {
        //创建任务集合
        List<CompletableFuture<List<ImportModel>>> list = new ArrayList<>();
        Map<Integer, List<Map<String, String>>> dataMap;
        int total = 0;
        try {
            dataMap = SaxParseExcelUtil.parseExcel(inputStream, importTemplate.getTitleStartRow(), importTemplate.getDataStartCol(), -1, importTemplate.getSheetNumber());
            List<ImportTemplateItem> items = importTemplate.getItems();
            Map<String, ImportTemplateItem> map = baseService.processItem(items, importTemplate.getSheetNumber());
            if (map.isEmpty()) { //配置项为空
                record.setStatus(ImportDataExcelStatus.IMPORT_FAILED);
                String fileId = baseService.generateTxt(Collections.singletonList("模板配置项为空"), batchNumber);
                record.setFileId(fileId);
            } else { //配置项不为空
                //验证配置项
                String msg = baseService.validItem(map, type);
                if (Objects.nonNull(msg)) { //配置项有误
                    record.setStatus(ImportDataExcelStatus.IMPORT_FAILED);
                    String fileId = baseService.generateTxt(Collections.singletonList(msg), batchNumber);
                    record.setFileId(fileId);
                } else { //配置项无误
                    for (Map.Entry<Integer, List<Map<String, String>>> sheetData : dataMap.entrySet()) {
                        Integer sheetIndex = sheetData.getKey();
                        List<Map<String, String>> sheetDataList = sheetData.getValue();
                        Map<String, String> titleMap = sheetDataList.get(0);
                        sheetDataList.remove(titleMap);
                        total += sheetDataList.size();
                        if (sheetDataList.size() < 1) {
                            throw new BadRequestException(null, "importExcelData", "importExcelData.is.fail");
                        }
                        //分页解析Excel中的数据对象,一页1000条
                        int pageSize = 2000;
                        int pageNumber = (int) Math.ceil((double) sheetDataList.size() / (double) pageSize);
                        for (int i = 0; i < pageNumber; i++) {
                            List<Map<String, String>> mapList = sheetDataList.stream().skip(i * pageSize).limit(pageSize).collect(Collectors.toList());
                            CompletableFuture<List<ImportModel>> task;
                            switch (type) {
                                case BILL_IMPORT:
                                    task = importBillFuture.processBillExcel(mapList, sheetIndex, batchNumber, map, i * pageSize, record, importTemplate);
                                    break;
                                case PRE_RECORD_IMPORT:
                                    task = importPreFuture.processPreRecordExcel(mapList, sheetIndex, batchNumber, map, i * pageSize, record, importTemplate);
                                    break;
                                case WORK_ORDER_IMPORT:
                                    task = importWorkOrderFuture.processWorkOrderExcel(mapList, sheetIndex, batchNumber, map, i * pageSize, record, importTemplate);
                                    break;
                                case WARNING_IMPORT:
                                    task = importWarningFuture.processWarningExcel(mapList, sheetIndex, batchNumber, map, i * pageSize, record, importTemplate);
                                    break;
                                case LEAVE_IMPORT:
                                    task = importLeaveFuture.processLeaveExcel(mapList, sheetIndex, batchNumber, map, i * pageSize, record, importTemplate);
                                    break;
                                case STOP_IMPORT:
                                    task = importStopFuture.processStopExcel(mapList, sheetIndex, batchNumber, map, i * pageSize, record, importTemplate);
                                    break;
                                default:
                                    task = null;
                                    break;
                            }
                            if (Objects.nonNull(task)) {
                                list.add(task);
                            }
                        }
                    }
                    List<ImportModel> models = new ArrayList<>();
                    for (CompletableFuture<List<ImportModel>> listCompletableFuture : list) {
                        models.addAll(listCompletableFuture.get());
                    }
                    //处理excel错误
                    List<String> errors = new ArrayList<>();
                    List<PaymentRecordModel> paymentRecordModels = new ArrayList<>();
                    List<PreRecordModel> preRecordModels = new ArrayList<>();
                    List<WorkOrderModel> workOrderModels = new ArrayList<>();
                    List<WarningModel> warningModels = new ArrayList<>();
                    List<LeaveCaseModel> leaveCaseModels = new ArrayList<>();
                    List<StopCaseModel> stopCaseModels = new ArrayList<>();
                    for (ImportModel model : models) {
                        if (Objects.nonNull(model.getPaymentRecordModel())) {
                            paymentRecordModels.add(model.getPaymentRecordModel());
                        }
                        if (Objects.nonNull(model.getPreRecordModel())) {
                            preRecordModels.add(model.getPreRecordModel());
                        }
                        if (Objects.nonNull(model.getWorkOrderModel())) {
                            workOrderModels.add(model.getWorkOrderModel());
                        }
                        if (Objects.nonNull(model.getWarningModel())) {
                            warningModels.add(model.getWarningModel());
                        }
                        if (Objects.nonNull(model.getLeaveCaseModel())) {
                            leaveCaseModels.add(model.getLeaveCaseModel());
                        }
                        if (Objects.nonNull(model.getStopCaseModel())) {
                            stopCaseModels.add(model.getStopCaseModel());
                        }
                        errors.addAll(model.getErrors());
                    }
                    if (!errors.isEmpty()) {
                        record.setStatus(ImportDataExcelStatus.IMPORT_FAILED);
                        String fileId = baseService.generateTxt(errors, batchNumber);
                        record.setFileId(fileId);
                    } else {
                        if (!paymentRecordModels.isEmpty()) {
                            RepositoryUtil.saveData(paymentRecordModelElastic, paymentRecordModels);
                        }
                        if (!preRecordModels.isEmpty()) {
                            RepositoryUtil.saveData(preRecordModelElastic, preRecordModels);
                        }
                        if (!workOrderModels.isEmpty()) {
                            RepositoryUtil.saveData(workOrderModelElastic, workOrderModels);
                        }
                        if (!warningModels.isEmpty()) {
                            RepositoryUtil.saveData(warningModelElastic, warningModels);
                        }
                        if (!leaveCaseModels.isEmpty()) {
                            RepositoryUtil.saveData(leaveCaseModelElastic, leaveCaseModels);
                        }
                        if (!stopCaseModels.isEmpty()) {
                            RepositoryUtil.saveData(stopCaseModelElastic, stopCaseModels);
                        }
                        record.setTotalNumber(total);
                        record.setStatus(ImportDataExcelStatus.IMPORT_SUCCESSFULLY);
                        record.process(userModel.getRealName(), ZWDateUtil.getNowDateTime());
                    }
                }
            }
            dataImportRecordElastic.save(record);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            record.setStatus(ImportDataExcelStatus.IMPORT_FAILED);
            String fileId = baseService.generateTxt(Collections.singletonList("导入模板有误"), Long.toString(new Date().getTime()));
            record.setFileId(fileId);
            dataImportRecordElastic.save(record);
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
            switch (type) {
                case BILL_IMPORT:
                    baseService.sendMsg(MessageType.IMPORT_BILL, userModel);
                    break;
                case PRE_RECORD_IMPORT:
                    baseService.sendMsg(MessageType.IMPORT_FOLLOW_RECORD, userModel);
                    break;
                case WORK_ORDER_IMPORT:
                    baseService.sendMsg(MessageType.IMPORT_WORKER_ORDER, userModel);
                    break;
                case WARNING_IMPORT:
                    baseService.sendMsg(MessageType.IMPORT_WARNING_INFO, userModel);
                    break;
                case LEAVE_IMPORT:
                    baseService.sendMsg(MessageType.IMPORT_LEFT_CASE, userModel);
                    break;
                case STOP_IMPORT:
                    baseService.sendMsg(MessageType.IMPORT_END_CASE, userModel);
                    break;
            }
        }
    }
}
